///******************** NG.Respate(C)  **********************************
//* 产品名称: Respate 科技
//* 文件名称: daemon.c
//* 程序作者: 雷帕特公司(南宫子萍)
//* 程序版本: V1.1														   
//* 编制日期: 2019/1/29
//* 功能描述: 守护进程
//* QQ:	2085827949
//**********************************************************************/

#include "lap_lib.h"

//#include <sys/types.h>
//#include <unistd.h>
//#include <stdlib.h>
//#include <stdio.h>
//#include <sys/stat.h>
//#include <fcntl.h>







/*********************************************************************************
** 函数名称: lap_getFile
** 功能描述: 指定路径下 得到文件
** 输入参数: src:文件路径			Path:分割后的路径 
** 输出参数: 文件名称  NULL:字符串结尾 非文件
** 返回参数: return response .
**********************************************************************************/
char buff[200]={0};
char* lap_getFile(const char* src,char *Path)
{
	char *temp1=NULL;
	char *temp2=NULL;
	char *temp3=NULL;

	//判断第一个字符是否为 '/'
	int flag = !strncmp(src,"/",1);
	
	memset(buff,0,sizeof(buff));
	strcpy(buff,src);
	
	if(src==NULL)
	{
		printf("lap_getFile err src:NULL\n");
		return NULL;
	}
	
	temp2 = strtok(buff,"/");

	while (1)
	{
		temp1 = strtok(NULL,"/");
		if(temp1 !=NULL)
		{
			temp3 = temp2;
			temp2 = temp1;
			if(temp3!=NULL)
			{
				if(flag)
					strcat(Path,"/");
				strcat(Path,temp3);
				flag=1;
			}
		}
		else break;
	}
	
	if(temp2!=NULL)
	{
		if(strstr(temp2,"."))
		{
			return temp2;
		}
		else
		{
			//为文件夹路径
			memset(Path,0,sizeof(Path));
			strcat(Path,src);
			return NULL;
		}
	}
	else return NULL;
}






//lap_creatFile("/root/project/temp1",NULL);
//lap_creatFile("/root/project/temp",NULL);
//lap_creatFile("/root/project/temp/","aa.c");
//lap_creatFile("/root/project/temp","bb.c");
//lap_creatFile(NULL,"temp/cc.h");
/*********************************************************************************
** 函数名称: lap_creatFile
** 功能描述: 创建一个文件的完整路径
** 输入参数: path:文件路径			file:文件名称 
** 输出参数: None.
** 返回参数: return response .
**********************************************************************************/
void lap_creatFile(const char * path,const char * file)
{

	char mkdir[100]="mkdir -p ";
	char touch[140]="touch ";
	char *t_path = (char *)path;
	char temp = 0;
	
	
	int ret = -1;

	if(path!=NULL)//文件路径不为空
	{
		if(file!=NULL)	//文件路径不为空 在path目录下 创建file文件
		{
			
			//判断path最后字符是否为'/'
			while(1)
			{
				t_path++;
				if(*t_path=='\0')	//最后一个字符
				{
					temp  = *(--t_path);
					break;
				}
			}
				
			//得到文件的全路径
			strcat(touch,path);
			if(temp !='/')
				strcat(touch,"/");
			
			strcat(touch,file);
		}
		else	//文件路径为空 文件为空 
		{
			char pbuff[140]={0};
			char* pfile =  NULL;
			
			pfile = lap_getFile(path,pbuff);
			if(pfile!=NULL)
			{
				lap_creatFile(pbuff,pfile);
				return ;
			}
		}
	}
	else 	//文件路径为空 即：在当前目录下创建文件	
	{
		if(file!=NULL)//文件不为空
		{
			//得到文件完整路径
			strcat(touch,file);
		}
		else	//文件路径 与文件皆为空 退出子程序
		{
			return ;
		}
		
	}

	//创建路径
	if(path!=NULL)
	{
		//得到 创建文件夹命令
		strcat(mkdir,path);
		//创建目录
		ret = system(mkdir);
		lap_errneg(ret,NULL,"lap_creatFile mkdir err!");//错误检查
	}
	
	//调试信息
	//printf("shell cmd: %s\n",mkdir);

	//创建文件
	if(file!=NULL)
	{
		ret = system(touch);
		lap_errneg(ret,NULL,"lap_creatFile touch err!");//错误检查
	}
}




//函数实现以下6点 便可以成为守护进程
/*
**	1.父进程先于子进程退出
**	2.子进程使用 setsid函数创建新的会话期，脱离控制台
**	3.调用 chdir 将当前工作目录设置为根目录'/'
**	4.umask设置为0 用于取消任何文件权限屏蔽
**	5.关闭所有文件描述符
**	6.将0、1、2 重定位到 /dev/null	(垃圾箱)
*/

/*********************************************************************************
** 函数名称: lap_daemon
** 功能描述: 将调用该函数的进程变为一个守护进程
** 输入参数: 输入参数: path:此守护进程的运行目录  传参为 NULL时：默认为 /root/lap
**			 传参为不存在路径时：自动创建该路径        
** 输出参数: None.
** 返回参数: return response .
**********************************************************************************/
#define DAEMON_DEF_DIR "/root/lap"	//守护进程的默认运行目录
void lap_daemon(const char * path)
{	
	pid_t pid;
	int ret = -1;
	char * dir = NULL;
	
	//子进程使用 setsid函数创建新的会话期，脱离控制台
	pid = setsid();
	lap_errneg(pid,NULL,"setsid erro!");	//错误检查

	if(path != NULL)	//自定义 守护进程的运行目录
	{
		dir = (char *)path;
	}
	else				//文件目录为空 使用默认运行目录
	{
		dir = DAEMON_DEF_DIR;
	}
	
	//创建目录
	lap_creatFile(dir,NULL);
	
	//调用 chdir 将当前工作目录设置   为默认目录
	ret = chdir(dir);
	lap_errneg(ret,NULL,"lap_daemon chdir err!");//错误检查

	//umask设置为0 用于取消任何文件权限屏蔽
	umask(0);

	//关闭所有文件描述符
	int cnt  = sysconf(_SC_OPEN_MAX);	//获取进程最大打开文件数目
	int i = 0;
	for (i=0;i<cnt;i++) close(i);

	//将0、1、2 (输入，输出，错误)重定位到 /dev/null	(垃圾箱)
	open("/dev/null",O_RDWR);
	open("/dev/null",O_RDWR);
	open("/dev/null",O_RDWR);
	
}

















#if 0	//功能测试
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	pid_t pid = -1;
	pid = fork();
	if( pid < 0 )		//子线程创建错误	
	{
		return -1;
	}
	else if( pid > 0 )	//父线程
	{
		printf("Parent fork  \n");
		return 0;
	}
		
	lap_daemon();
	while (1)
	{
		
	}
	
	return 0;
}
#endif







																						 
